Web におけるキャッシュ
ブラウザが持つ従来のキャッシュ機構について
キャッシュを行う意義
リソースの取得の高速化
サーバーへの負担減
HTTP ヘッダーによるキャッシュ
ブラウザはリクエストを発行せず、保持するキャッシュを使用
Cache-Control, Expires
ブラウザはリクエストを発行してサーバーへキャッシュの有効性を確認してからキャッシュを使用する
ETag, Last-Modified
キャッシュは「再利用」を行う目的である一方、ある一定の範囲で「更新」も行いたいという相反するコントロールが求められる
Cache-Control, Expires
Cache-Control - HTTP | MDN
Cache-Control ヘッダーで max-age を指定するか Expires で未来の時間を指定すると、ブラウザはその期間内であればサーバーに問い合わせしないでキャッシュを使用する
この指定によるキャッシュがヒットする場合、ネットワークパケットは一切発生せず、理論上は最速でリソースを取得することができる
しかし、期限切れまではサーバーは介入できない
長い期間にすると配信したスクリプトにバグが会った時に困る
短いとキャッシュの効果が薄くなる
そこで現実的には期間を長く(推奨される最大値の 1 年などを指定)し、更新があったらリソースの URL を変更するという運用がよく行われる
code:html
<!-- ver=1 を参照している間はキャッシュが用いられる -->
<script src="production.min.js?ver=1"></script>
<!-- JS が更新されたら ver=2 と URL を変更する -->
<script src="production.min.js?ver=2"></script>
ブラウザのキャッシュは基本的には URL 単位で行われるため、URL を毎回変えてやれば古いキャッシュが使われることを避けることができる
あくまでも URL を変えることが目的なのでサーバー側でハンドルする必要は特にない
バージョンの代わりにタイムスタンプやハッシュなどでもよい
ただし、この <script> を含む、index.html 自体が長期間キャッシュされてしまうと、production.min.js の URL も更新できない
index.html 自体は長期間のキャッシュがしにくいという問題は残る
ETag, Last-Modified
HTTP には Conditional GET という仕組みがある
「すでに保持しているキャッシュが今でも有効であるか 」をサーバーに問い合わせる方法
サーバーは ETag, Last-Modified などのヘッダーをレスポンスに付与することで、リソースに関する情報をクライアントに伝える
クライアントはその情報を次のコンテントネゴシエーションに利用して、キャッシュの再利用性について判断する
Stale-While-Revalidate
Cache-Control, Expires
ETag, Last-Modified
これらは下手に設定すると更新されないし、弱気に設定すると効果が薄れるという難しさがある
ヘッダーのみを用いて、「キャッシュは効かせたいが、なるべく新鮮なリソースを提供したい」などといった要望には対処が困難であった
そこで提案されたのが Stale-While-Revalidate(SwR)というCache-Control の拡張
簡単に言えば、「キャッシュから表示するが、裏で非同期的にキャッシュを更新しておく」という仕組み